package interview.a1b2c3;

/**
 * @author: 李德才
 * @description:
 * @create: 2020-12-19 11:06
 **/


/**
 * 两个线程分别输出 A-Z 和 1-26 ，
 * 要求两个线程交替输出
 * 即：A1B2C3D4
 */
public class Test_01_notify_wait {
    public static final String[] LETTER_ARRAY = new String[]{"A", "B", "C", "D", "E", "F"};
    public static final String[] NUMBER_ARRAY = new String[]{"1", "2", "3", "4", "5", "6"};


    /**
     * 一个线程修改了一个对象的值，而另一个线程感知到了变化，然后进行相应的操作，整个过程开始于一个线程，而最终执行又是另外一个线程。
     * 前者是生产者，后者是消费者，这种模式隔离了“做什么”（What）和“怎么做”（How），在功能层面上实现了解耦，体系结构上具备良好的伸缩性，
     */

    /**
     * 创建一个对象（object），用于设置锁的状态
     * 让两个线程使用 synchronized 的方式锁住同一个对象（object）
     */
    static final Object object = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            try {
//                1、锁住对象
                synchronized (object) {
//                    2、循环数组
                    for (String str : LETTER_ARRAY) {
//                        3、输出一个元素
                        System.err.println(str);
//                        4、// 唤醒其他线程 (t2)
                        object.notify();
//                        5、当前线程进入等待状态,等待 t2 叫醒自己，********  需要注意， 调用wait()方法后，会释放对象的锁 ********
                        object.wait();
//                        注意上面的代码执行后将不会执行下面的输出，线程进入阻塞状态
                        System.err.println("####");
                    }
                    object.notify();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t1").start();

        new Thread(() -> {
            try {
//
                synchronized (object) {
                    for (String str : NUMBER_ARRAY) {
                        System.err.println(str);
                        object.notify(); //唤醒其他线程 (t1)
                        object.wait(); //当前线程进入等待状态,等待 t1 叫醒自己
                    }
                    object.notify();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t2").start();
    }
}
